package org.summerframework.component.security.oauth.alipay;

import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.request.AlipaySystemOauthTokenRequest;
import com.alipay.api.request.AlipayUserInfoShareRequest;
import com.alipay.api.response.AlipaySystemOauthTokenResponse;
import com.alipay.api.response.AlipayUserInfoShareResponse;
import org.summerframework.component.security.oauth.LoginType;
import org.summerframework.component.security.oauth.OAuthAppIdAndAppSecret;
import org.summerframework.component.security.oauth.OAuthResultCode;
import org.summerframework.component.security.oauth.exception.OAuthException;
import org.apache.commons.lang3.StringUtils;

public class AlipayOAuthSupper implements AlipayOAuthInterceptor {

    private final AlipayAppIdAndAppSecret alipayAppIdAndAppSecret;

    private AlipayClient alipayClient;

    public AlipayOAuthSupper(AlipayAppIdAndAppSecret alipayAppIdAndAppSecret) {
        this.alipayAppIdAndAppSecret = alipayAppIdAndAppSecret;
        alipayClient = new DefaultAlipayClient(alipayAppIdAndAppSecret.getGateway(), alipayAppIdAndAppSecret.getAppId(), alipayAppIdAndAppSecret.getPrivateKey(), "json", alipayAppIdAndAppSecret.getCharset(), alipayAppIdAndAppSecret.getPublicKey(), alipayAppIdAndAppSecret.getSignType());
    }

    @Override
    public AlipayUserInfo getResultInfo(AlipayAccessToken alipayAccessToken) {
        AlipayUserInfo alipayUserInfo = new AlipayUserInfo();
        AlipaySystemOauthTokenRequest request = new AlipaySystemOauthTokenRequest();
        request.setCode(alipayAccessToken.getCode());
        request.setGrantType("authorization_code");

        try {
            AlipaySystemOauthTokenResponse response = alipayClient.execute(request);

            if (!response.isSuccess()) {
                throw new OAuthException(OAuthResultCode.ILLEGAL_ARGUMENT, response.getSubMsg());
            }

            alipayUserInfo.setAuthToken(response.getAccessToken());
            alipayUserInfo.setRefreshToken(response.getRefreshToken());
            alipayUserInfo.setExpiresIn(response.getExpiresIn());
            alipayUserInfo.setReExpiresIn(response.getReExpiresIn());
            alipayUserInfo.setUserId(response.getUserId());

        } catch (AlipayApiException e) {
            throw new OAuthException(OAuthResultCode.ILLEGAL_ARGUMENT, e.getMessage(), e);
        }

        return alipayUserInfo;
    }

    @Override
    public AlipayUserInfo getInfo(AlipayUserInfo alipayUserInfo) {
        AlipayUserInfoShareRequest request = new AlipayUserInfoShareRequest();
        AlipayUserInfoShareResponse response;

        try {
            response = alipayClient.execute(request, alipayUserInfo.getAuthToken());

            if (!response.isSuccess()) {
                throw new OAuthException(OAuthResultCode.ILLEGAL_ARGUMENT, response.getSubMsg());
            }

            alipayUserInfo.setUserId(response.getUserId());
            alipayUserInfo.setAvatar(response.getAvatar());
            alipayUserInfo.setCity(response.getCity());
            alipayUserInfo.setIsCertified(StringUtils.equals(response.getIsCertified(), "T") ? 1 : 0);
            alipayUserInfo.setIsStudentCertified(StringUtils.equals(response.getIsStudentCertified(), "T") ? 1 : 0);
            alipayUserInfo.setNickname(response.getNickName());
            alipayUserInfo.setProvince(response.getProvince());
            alipayUserInfo.setSex(response.getGender() != null && response.getGender().equals("M") ? 1 : 2);
            alipayUserInfo.setUserType(response.getUserType() != null ? Integer.valueOf(response.getUserType()) : null);
            alipayUserInfo.setUserStatus(response.getUserStatus());
        } catch (AlipayApiException e) {
            throw new OAuthException(OAuthResultCode.ILLEGAL_ARGUMENT, e.getErrMsg(), e);
        }

        return alipayUserInfo;
    }

    @Override
    public OAuthAppIdAndAppSecret getOAuthInfo() {
        return alipayAppIdAndAppSecret;
    }

    @Override
    public boolean supportsType(LoginType loginType) {
        return LoginType.ALIPAY == loginType;
    }

    @Override
    public AlipayAccessToken getAccessToken(String code) {
        return new AlipayAccessToken(code);
    }
}
